package com.bestcem.xm.award.service.impl;

import com.bestcem.xm.award.constant.Constants;
import com.bestcem.xm.award.constant.RedisKeyConstant;
import com.bestcem.xm.award.constant.RequestAwardConstants;
import com.bestcem.xm.award.dao.BandPointDao;
import com.bestcem.xm.award.entity.mongo.BaseEntity;
import com.bestcem.xm.award.entity.pojo.AwardAwardDO;
import com.bestcem.xm.award.entity.pojo.AwardRequestDO;
import com.bestcem.xm.award.entity.pojo.BandPointDO;
import com.bestcem.xm.award.enums.AwardRequestStatusEnum;
import com.bestcem.xm.award.enums.AwardTypeEnum;
import com.bestcem.xm.award.enums.RecordFlagStatusEnum;
import com.bestcem.xm.award.service.PointAwardDrawService;
import com.bestcem.xm.award.service.PointAwardService;
import com.bestcem.xm.award.service.bo.award.AwardAwardBO;
import com.bestcem.xm.award.service.bo.point.PointAwardBO;
import com.bestcem.xm.award.service.dto.awardaward.UpdateAwardStatusDTO;
import com.bestcem.xm.award.service.dto.requestaward.PointAwardDTO;
import com.bestcem.xm.award.service.dto.requestaward.RequestAwardDTO;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.common.core.uitls.JsonUtil;
import com.bestcem.xm.componet.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Optional;

import static com.bestcem.xm.award.enums.AwardRequestStatusEnum.PASS;
import static com.bestcem.xm.award.enums.AwardStatusEnum.*;
import static com.bestcem.xm.award.enums.AwardTypeEnum.POINT;

/**
 * 积分奖励创建修改
 *
 * @author xa.zhang <xa.zhang@idiaoyan.com>
 * @version v1.0
 * @date 2021/6/30 17:47
 */
@Slf4j
@Service("pointAwardService")
public class PointAwardServiceImpl extends AbstractAwardAwardService implements PointAwardService {

    @Resource
    private BandPointDao bandPointDao;
    @Resource
    private PointAwardDrawService pointAwardDrawService;
    @Resource
    private RedisService redisService;
    /**
     * 更新奖励状态
     *
     * @param updateAwardStatusDTO 更新奖励入参
     * @return 结果
     */
    @Override
    public ServiceResult<String> updateAwardStatus(UpdateAwardStatusDTO updateAwardStatusDTO) {
        // 检查是否可以更新到新状态
        if (!checkUpdateStatus(updateAwardStatusDTO.getStatus(), updateAwardStatusDTO.getOldStatus())) {
            return ServiceResult.fail("当前状态无法转移至新状态！");
        }
        // 再次检查
        AwardAwardDO awardAwardDO = awardAwardDao.findById(updateAwardStatusDTO.getAwardId());
        if (awardAwardDO == null) {
            return ServiceResult.fail("奖励不存在！");
        }
        Integer newStatus = updateAwardStatusDTO.getStatus();
        Integer oldStatus = updateAwardStatusDTO.getOldStatus();

        //如果改为激活状态，那么设置积分数量
        if (newStatus.intValue() == ACTIVE.getIndex() && oldStatus.intValue() == INACTIVE.getIndex()) {
            awardAwardDao.startBonusAward(awardAwardDO.getId(), awardAwardDO.getBasic().getStartTime());
            //如果有总数限制
            if (awardAwardDO.getBandPoint().getTotal() != null) {
                //redis key设置总数
                redisService.set(String.format(RedisKeyConstant.AWARD_POINT_WAIT_COUNT, awardAwardDO.getId()), "" + awardAwardDO.getBandPoint().getTotal());
            }
            // 更新状态
//            Update update = Update.update(STATUS, newStatus);
            AwardAwardDO update = new AwardAwardDO();
            update.setStatus(newStatus);
            if (update.getBasic() == null) {
                update.setBasic(new AwardAwardDO.Basic());
            }
            update.getBasic().setStartTime(DateUtil.getDate());
            // 如果是激活，保存激活时间
            awardAwardDao.updateByAwardId(updateAwardStatusDTO.getAwardId(), update);
            return ServiceResult.success(awardAwardDO.getId());
        } else {
            //如果结束了，那么删除redis中保存的奖池
            if (newStatus.intValue() == FINISH.getIndex() && awardAwardDO.getBandPoint() != null && awardAwardDO.getBandPoint().getTotal() != null) {
                redisService.del(String.format(RedisKeyConstant.AWARD_POINT_WAIT_COUNT, awardAwardDO.getId()));
            }

            AwardAwardDO update = new AwardAwardDO();
            update.setStatus(updateAwardStatusDTO.getStatus());

            long modifiedCount = awardAwardDao.updateByIdAndStatus(updateAwardStatusDTO.getAwardId(), updateAwardStatusDTO.getOldStatus(), update);
            if (modifiedCount == 1) {
                return ServiceResult.success();
            } else {
                return ServiceResult.fail("更新失败，请重试！");
            }
        }

    }

    /**
     * 前置校验
     *
     * @param requestAwardDTO 参数
     * @return 结果
     */
    @Override
    public ServiceResult<String> doRequestAward(RequestAwardDTO requestAwardDTO) {
        // 奖励id
        String awardId = Optional.ofNullable(requestAwardDTO).map(RequestAwardDTO::getAwardAwardDO)
                .map(BaseEntity::getId).orElse(Constants.BLANK);
        if (StringUtils.isBlank(awardId)) {
            return ServiceResult.fail(RequestAwardConstants.MISSING_AWARD_ID);
        }

        //校验当前时间是否在奖励开始时间与结束时间期间
        AwardRequestStatusEnum checkInProceeding = awardCheck.checkInProceeding(requestAwardDTO);
        if (checkInProceeding.getIndex() != PASS.getIndex()) {
            return super.checkFail(requestAwardDTO.getAwardRequestDO(), checkInProceeding);
        }

        // 待插入AWARD_REQUEST数据
        AwardRequestDO request = requestAwardDTO.getAwardRequestDO();
        if (request == null) {
            return ServiceResult.fail(RequestAwardConstants.MISSING_AWARD_REQUEST);
        }

        // 奖励信息
        AwardAwardDO awardAwardDO = requestAwardDTO.getAwardAwardDO();

        // 校验答题时间
        AwardRequestStatusEnum checkCostTime = awardCheck.getCheckCostTimeResult(requestAwardDTO);
        if (checkCostTime.getIndex() != PASS.getIndex()) {
            request.setStatus(checkCostTime.getIndex());
            AwardRequestDO awardRequestDO = awardRequestDao.insert(request);

            return ServiceResult.fail(checkCostTime.getName());
        }

        //检查积分奖励剩余次数
        if (!pointAwardDrawService.checkWaitCount(awardAwardDO)) {
            request.setStatus(AwardRequestStatusEnum.TOTAL.getIndex());
            AwardRequestDO awardRequestDO = awardRequestDao.insert(request);
            return ServiceResult.fail(AwardRequestStatusEnum.TOTAL.getName());
        }


        request.setStatus(PASS.getIndex());
        // 插入AWARD_REQUEST数据
        AwardRequestDO awardRequestDO = awardRequestDao.insert(request);
        String requestId = Optional.ofNullable(awardRequestDO).map(AwardRequestDO::getId).orElse(Constants.BLANK);
        if (StringUtils.isBlank(requestId)) {
            return ServiceResult.fail(RequestAwardConstants.AWARD_REQUEST_SAVE_ERROR);
        }

        PointAwardDTO pointAwardDTO = new PointAwardDTO();
        pointAwardDTO.setRequestId(requestId);
        pointAwardDTO.setPointAward(PointAwardBO.createAwardVO(awardAwardDO));

        String data = JsonUtil.transferToJsonSnake(pointAwardDTO);
        return ServiceResult.success(data);
    }

    /**
     * 积分奖励类型
     *
     * @return 积分奖励类型
     */
    @Override
    public AwardTypeEnum getAwardTypeEnum() {
        return POINT;
    }

    /**
     * 奖励类型单独检查是否可以更新或修改
     *
     * @param awardAward 奖励数据
     * @return 结果
     */
    @Override
    public ServiceResult<String> independentCheckAward(AwardAwardBO awardAward) {
        if (awardAward == null) {
            return ServiceResult.fail("缺少参数");
        }
        if (awardAward.getBasic().getStopTime().compareTo(awardAward.getBasic().getStartTime()) < 0) {
            return ServiceResult.fail("结束时间不能在开始时间或当前时间之前!");
        }

        String bandPointId = awardAward.getBandPoint().getPointId();
        BandPointDO bandPoint = bandPointDao.selectByPrimaryKey(bandPointId);
        if (bandPoint == null) {
            return ServiceResult.fail("品牌积分id错误");
        }

        if (bandPoint.getRecordFlag().intValue() == RecordFlagStatusEnum.INVALID.getIndex()) {
            return ServiceResult.fail("品牌积分已被删除，无法使用");
        }
        String savedCode = bandPoint.getCode() == null ? "" : bandPoint.getCode();
        String paramCode = awardAward.getBandPoint().getCode() == null ? "" : awardAward.getBandPoint().getCode();

        if (!(savedCode.equals(paramCode) && bandPoint.getName().equals(awardAward.getBandPoint().getPointName()))) {
            return ServiceResult.fail("品牌积分跟数据库记录的不一致，请重新选择");
        }

        return ServiceResult.success();
    }

    @Override
    public ServiceResult<String> beforeFinishAward(String awardId) {
        redisService.del(String.format(RedisKeyConstant.AWARD_POINT_WAIT_COUNT, awardId));
        return ServiceResult.success();
    }

}